using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
using Sedna.Core.Controller;
using Sedna.Core.Controller.Common;

namespace Sedna.Core.Security
{
    /// <summary>
    /// Action that can be executed on a page
    /// </summary>
    public class SecureAction : AbstractAction, ISecureAction
    {
        protected String name;

        /// <summary>
        /// A list of permissions required to execute the action (at least one of them)
        /// </summary>
        protected IList executePermissions;

        /// <summary>
        /// Access policies (view & edit) that should be applied to page's controls
        /// </summary>
        protected IList accessPolicies;

        /// <summary>
        /// Action that will be executed before applying access policies
        /// </summary>
        protected IAction task;
       
        protected bool returnTaskResult;

        # region Properties

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public IList ExecutePermissions
        {
            set { executePermissions = value; }
        }

        public IList AccessPolicies
        {
            set { accessPolicies = value; }
        }

        public IAction Task
        {
            get { return task; }
            set { task = value; }
        }

        public bool ReturnTaskResult
        {
            get { return returnTaskResult; }
            set { returnTaskResult = value; }
        }

        # endregion

        public virtual bool CanExecute(IPrincipalWrapper principalWrapper, IExecutionContext executionContext)
        {
            if (principalWrapper == null || executePermissions == null || executePermissions.Count == 0)
            {
                return true;
            }
            
            foreach (string permission in executePermissions)
            {
                if (principalWrapper.IsInRole(permission))
                {
                    return true;
                }
            }
            
            return false;
        }

        public override IActionResult Execute(IExecutionContext executionContext)
        {
            if (task != null)
            {
                IActionResult taskResult = task.Execute(executionContext);

                if (returnTaskResult)
                    return taskResult;
            }
            
            return CreateResult(successStatus);
        }

        public virtual void ApplyPolicy(IPrincipalWrapper principalWrapper, IExecutionContext executionContext)
        {
            if (accessPolicies == null)
                return;

            foreach (IAccessPolicy policy in accessPolicies)
            {
                policy.Apply(principalWrapper, executionContext);
            }
        }
    }
}
